package com.aop.SpElAop.ExpressionParser;

/**
 * @Package: com.aop.SpElAop
 * @ClassName: LogValueParser
 * @Author: wulongkai
 * @CreateTime: 2024/7/9 11:05
 * @Description:
 */

import com.aop.SpElAop.ExpressionParser.CommonExpressionEvaluator;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.context.expression.AnnotatedElementKey;
import org.springframework.expression.EvaluationContext;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.function.Supplier;

/**
 * 包装参数发给{@link CommonExpressionEvaluator}解析的工具类
 * 参考：
 * SpringBoot 自定义注解实现切面日志并使用SpEL解析日志模板
 *      https://juejin.cn/post/7021093810465669128
 * el 表达式 https://juejin.cn/post/7300779071389532214
 */
@Component
public class ValueParser implements BeanFactoryAware {

    @Nullable
    private BeanFactory beanFactory;

    private final CommonExpressionEvaluator commonExpressionEvaluator = new CommonExpressionEvaluator();

    @Override
    public void setBeanFactory(@NonNull BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    public <T> T parse(ProceedingJoinPoint point, Supplier<String> getExpression, @Nullable Object result, @Nullable String errorMsg, Class<T> parserResultClass) {
        Method method = ((MethodSignature) point.getSignature()).getMethod();
        Class<?> targetClass = point.getTarget().getClass();
        EvaluationContext evaluationContext = commonExpressionEvaluator.createEvaluationContext(
                method, point.getArgs(), point.getTarget(), targetClass, result, errorMsg, beanFactory
        );
        AnnotatedElementKey methodKey = new AnnotatedElementKey(method, targetClass);
        return commonExpressionEvaluator.parse(getExpression.get(), methodKey, evaluationContext, parserResultClass);
    }
}


